package cn.getech.data.development.controller;


import cn.getech.data.development.constant.*;
import cn.getech.data.development.dto.MaskTableSearchDto;
import cn.getech.data.development.entity.CusMaskUdf;
import cn.getech.data.development.entity.DataPermissionParam;
import cn.getech.data.development.entity.TableFieldMaskRules;
import cn.getech.data.development.entity.TableInfo;
import cn.getech.data.development.model.dto.TableFieldInfoDto;
import cn.getech.data.development.model.dto.TableFieldMaskRulesDto;
import cn.getech.data.development.model.dto.TableInfoDto;
import cn.getech.data.development.model.vo.*;
import cn.getech.data.development.service.*;
import cn.getech.data.development.vo.MaskTableInfoVO;
import cn.getech.data.intelligence.common.exception.RRException;
import cn.getech.data.intelligence.common.utils.PageUtils;
import cn.getech.data.intelligence.common.utils.PojoUtils;
import cn.getech.data.intelligence.common.utils.R;
import cn.getech.system.center.annotation.SysLog;
import cn.getech.system.center.constant.OperationModulesEnum;
import cn.getech.system.center.constant.OperationTypeEnum;
import cn.getech.system.center.constant.module.ModuleEnum;
import cn.getech.system.center.model.dto.SysUserDto;
import cn.getech.system.center.service.SysUserService;
import cn.getech.system.center.utils.ShiroUtils;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import io.swagger.annotations.ApiOperation;
import jodd.util.StringUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author hujz
 * @since 2020-02-19
 */
@RestController
@RequestMapping("/bdp/tableFieldMaskRules")
public class TableFieldMaskRulesController {

    @Autowired
    private ITableFieldMaskRulesService iTableFieldMaskRulesService;

    @Autowired
    private IDataPermissionParamService iDataPermissionParamService;

    @Autowired
    private RangerDataService rangerDataService;

    @Autowired
    private CusMaskUdfService cusMaskUdfService;

    @Autowired
    private TableInfoService tableInfoService;

    @Autowired
    private SysUserService sysUserService;

    @ApiOperation("查询未配置脱敏规则的字段列表")
    @GetMapping("/notDataMaskingField/{id}")
    //@SysLog(value="查询未配置脱敏规则的字段列表",type= OperationTypeEnum.SELECTCODE, modulesType = OperationModulesEnum.SYSMODECODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    public R notDataMaskingField(@PathVariable("id") Integer id) {
        //查询没有配置过脱敏规则的字段
        List<TableFieldInfoDto> rest = iTableFieldMaskRulesService.listNotDataMaskingField(id);
        return R.okWithData(PojoUtils.listConvert(TableFieldInfoVO.class, rest));
    }


    @ApiOperation("查询脱敏方式列表")
    @GetMapping("/dataMaskingType")
    //@SysLog(value="查询脱敏方式列表",type= OperationTypeEnum.SELECTCODE, modulesType = OperationModulesEnum.SYSMODECODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    public R dataMaskingType() {
        List<JSONObject> data = new ArrayList<>();
        for (RangerMaskType e : RangerMaskType.values()) {
            JSONObject obj = new JSONObject();
            //暂时不开放自定义的udf
            if (RangerMaskType.MASK_CUSTOM.getId() == e.getId()) {
                continue;
            }
            obj.put("id", e.getId());
            obj.put("name", e.getPageName());
            obj.put("desc", e.getDesc());
            data.add(obj);
        }
        //查询默认的内置的udf函数
        List<CusMaskUdf> list = cusMaskUdfService.list();
        if (CollectionUtil.isNotEmpty(list)) {
            for (CusMaskUdf cusMaskUdf : list) {
                JSONObject obj = new JSONObject();
                obj.put("id", cusMaskUdf.getId());
                obj.put("name", cusMaskUdf.getMenothName());
                obj.put("desc", cusMaskUdf.getUdfFuncDesc());
                data.add(obj);
            }
        }
        return R.okWithData(data);
    }

    @ApiOperation("查询表对应的配置的数据脱敏规则的配置信息")
    @GetMapping("/dataMasking/{id}")
    //@SysLog(value="查询表对应的配置的数据脱敏规则的配置信息",type= OperationTypeEnum.SELECTCODE, modulesType = OperationModulesEnum.SYSMODECODE,platformModuleType = ModuleEnum.DATA_MAP_MODULE_CODE)
    public R dataMasking(@PathVariable("id") Integer id) {

        TableInfoDto tableInfoDto = iTableFieldMaskRulesService.getByTableId(id);
        if (null == tableInfoDto) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_NOT_FOUND.getMessage());
        }
        TableInfoAndMaskingVO tableInfoAndMaskingVO = new TableInfoAndMaskingVO();
        BeanUtils.copyProperties(tableInfoDto, tableInfoAndMaskingVO);
        //如果是null 转变成为""空的字符串
        if (null == tableInfoDto.getTableMaskWhiteList()) {
            tableInfoAndMaskingVO.setTableMaskWhiteList("");
        }
        //设置对应的所有的数据库等级
        List<DataPermissionParam> dataPermissionParams = iDataPermissionParamService.list(new QueryWrapper<DataPermissionParam>().eq("permiss_type", 1));
        tableInfoAndMaskingVO.setAllTableLevel(PojoUtils.listConvert(DataPermissionParamVO.class, dataPermissionParams));

        //设置所有的查询出来的数据脱敏规则
        List<TableFieldMaskRulesDto> tableFieldMaskRulesDtos = iTableFieldMaskRulesService.listDataMaskingField(id,ShiroUtils.getTenantId());
        tableInfoAndMaskingVO.setTableFieldMaskRulesVOS(PojoUtils.listConvert(TableFieldMaskRulesVO.class, tableFieldMaskRulesDtos));

        return R.okWithData(tableInfoAndMaskingVO);
    }


    @ApiOperation("保存数据脱敏的开关和白名单信息")
    @PostMapping("/saveDataMaskingOpenInfo")
    @SysLog(value = "保存数据脱敏的开关和白名单信息", type = OperationTypeEnum.UPDATECODE, modulesType = OperationModulesEnum.SYSMODECODE, platformModuleType = ModuleEnum.PROJECT_LIST_MODULE_CODE)
    public R saveDataMaskingOpenInfo(@RequestBody TableInfoAndOpenVO tableInfoAndOpenVO) {
        //表id和对应的开关必须得传
        Assert.notNull(tableInfoAndOpenVO, DataDevelopmentBizExceptionEnum.PARAM_ERROR.getMessage());
        if (null == tableInfoAndOpenVO.getId()) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_ID_NOT_FOUND.getMessage());
        }
        if (null == tableInfoAndOpenVO.getTableMaskOpen()) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_MASK_RULES_NOT_FOUND.getMessage());
        }
        TableInfoDto tableInfoDto = new TableInfoDto();
        BeanUtils.copyProperties(tableInfoAndOpenVO, tableInfoDto);
        iTableFieldMaskRulesService.saveTableMaskOpen(tableInfoDto);
        rangerDataService.saveRangerPolicyMasking(tableInfoAndOpenVO.getId());
        return R.ok();
    }


    @ApiOperation("保存数据脱敏的字段规则")
    @PostMapping("/saveDataMaskingTableField")
    @SysLog(value = "保存数据脱敏的字段规则", type = OperationTypeEnum.UPDATECODE, modulesType = OperationModulesEnum.SYSMODECODE, platformModuleType = ModuleEnum.PROJECT_LIST_MODULE_CODE)
    public R saveDataMaskingTableField(@RequestBody TableFieldMaskVO tableFieldMaskVO) {
        Assert.notNull(tableFieldMaskVO, DataDevelopmentBizExceptionEnum.PARAM_ERROR.getMessage());
        if (null == tableFieldMaskVO.getMaskType()) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_MASK_TYPE_ID_NOT_FOUND.getMessage());
        }
        if (null == tableFieldMaskVO.getTableFieldId()) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_FIELD_ID_NOT_FOUND.getMessage());
        }
        TableFieldMaskRulesDto tableFieldMaskRulesDto = new TableFieldMaskRulesDto();
        BeanUtils.copyProperties(tableFieldMaskVO, tableFieldMaskRulesDto);
        TableFieldMaskRules tableFieldMaskRules = iTableFieldMaskRulesService.saveTableFieldRules(tableFieldMaskRulesDto);
        //生对应的策略
        rangerDataService.saveRangerPolicyMaskingByTableFieldId(tableFieldMaskRules.getTableFieldId());
        return R.okWithData(tableFieldMaskRules.getId());
    }

    @ApiOperation("保存数据脱敏规则")//合并saveDataMaskingTableField和saveDataMaskingOpenInfo接口
    @PostMapping("/saveDataMaskingInfo")
    @SysLog(value = "保存数据脱敏规则", type = OperationTypeEnum.UPDATECODE, modulesType = OperationModulesEnum.SYSMODECODE, platformModuleType = ModuleEnum.PROJECT_LIST_MODULE_CODE)
    public R saveDataMaskingInfo(@RequestBody MaskInfoVO maskInfoVO) {
        Assert.notNull(maskInfoVO, DataDevelopmentBizExceptionEnum.PARAM_ERROR.getMessage());
        List<TableFieldMaskRulesDto> tableFieldMaskRulesDtos = iTableFieldMaskRulesService.listDataMaskingField(maskInfoVO.getId(),ShiroUtils.getTenantId());
        //先删除规则
        if (tableFieldMaskRulesDtos != null) {
            for (TableFieldMaskRulesDto tableFieldMaskRulesDto : tableFieldMaskRulesDtos) {
                deleteDataMaskingTableField(tableFieldMaskRulesDto.getId());
            }
        }
        //再创建规则
        if (maskInfoVO.getTableFieldMaskListVO() != null) {
            for (TableFieldMaskVO tableFieldMaskVO : maskInfoVO.getTableFieldMaskListVO()) {
                R r = saveDataMaskingTableField(tableFieldMaskVO);
                Integer tableFieldMaskId = (Integer) r.get("data");
                tableFieldMaskVO.setId(tableFieldMaskId);
            }
        }
        saveDataMaskingOpenInfo((TableInfoAndOpenVO) maskInfoVO);
        return R.okWithData(maskInfoVO);
    }


    @ApiOperation("修改数据脱敏的字段规则")
    @PostMapping("/updateDataMaskingTableField")
    @SysLog(value = "修改数据脱敏的字段规则", type = OperationTypeEnum.UPDATECODE, modulesType = OperationModulesEnum.SYSMODECODE, platformModuleType = ModuleEnum.PROJECT_LIST_MODULE_CODE)
    public R updateDataMaskingTableField(@RequestBody TableFieldMaskVO tableFieldMaskVO) {

        Assert.notNull(tableFieldMaskVO, DataDevelopmentBizExceptionEnum.PARAM_ERROR.getMessage());
        if (null == tableFieldMaskVO.getId()) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_MASK_RULES_ID_NOT_FOUND.getMessage());
        }
        if (null == tableFieldMaskVO.getMaskType()) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_MASK_TYPE_ID_NOT_FOUND.getMessage());
        }
        if (null == tableFieldMaskVO.getTableFieldId()) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_FIELD_ID_NOT_FOUND.getMessage());
        }
        TableFieldMaskRulesDto tableFieldMaskRulesDto = new TableFieldMaskRulesDto();
        BeanUtils.copyProperties(tableFieldMaskVO, tableFieldMaskRulesDto);
        TableFieldMaskRules tableFieldMaskRules = iTableFieldMaskRulesService.getById(tableFieldMaskVO.getId());
        if (null == tableFieldMaskRules) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_MASK_RULES_ID_NOT_FOUND.getMessage());
        }
        //再更新
        iTableFieldMaskRulesService.updateTableFieldRules(tableFieldMaskRulesDto);
        //更新显示类型
        if (!Objects.equals(tableFieldMaskVO.getMaskType(), tableFieldMaskRules.getMaskType())) {
            rangerDataService.saveRangerPolicyMaskingByTableFieldId(tableFieldMaskRules.getTableFieldId());
        }
        return R.ok();
    }


    @ApiOperation("删除数据脱敏的字段规则")
    @PostMapping("/deleteDataMaskingTableField/{id}")
    @SysLog(value = "删除数据脱敏的字段规则", type = OperationTypeEnum.DELETECODE, modulesType = OperationModulesEnum.SYSMODECODE, platformModuleType = ModuleEnum.PROJECT_LIST_MODULE_CODE)
    public R deleteDataMaskingTableField(@PathVariable("id") Integer id) {
        //查询到这个规则信息
        TableFieldMaskRules tableFieldMaskRules = iTableFieldMaskRulesService.getById(id);
        if (null == tableFieldMaskRules) {
            throw new RRException(DataDevelopmentBizExceptionEnum.TABLE_MASK_RULES_ID_NOT_FOUND.getMessage());
        }
        iTableFieldMaskRulesService.deleteById(id);
        rangerDataService.deleteRangerPolicyMasking(tableFieldMaskRules.getTableFieldId());
        return R.ok();
    }


    @ApiOperation("数据脱敏列表")
    @PostMapping("/tableList")
    public R tableList(@RequestBody MaskTableSearchDto maskTableSearchDto) {
        Map params = new HashMap();
        Long userId = ShiroUtils.getUserId();
        params.put("create_per", userId);
        params.put("appUser", userId);
        params.put("sidx", "id");
        params.put("order", "desc");
        if (StringUtils.isNotBlank(maskTableSearchDto.getDbName())) {
            params.put("db_name", maskTableSearchDto.getDbName());
        }

        if (maskTableSearchDto.getCreateUserId() != null && maskTableSearchDto.getCreateUserId() > 0) {
            params.put("userId", maskTableSearchDto.getCreateUserId());
        }

        if (maskTableSearchDto.getStoreEngine() != null && maskTableSearchDto.getStoreEngine() > 0) {
            params.put("store_engine", maskTableSearchDto.getStoreEngine());
        }

        //增加表id入参，查询单表的配置信息

        params.put("limit", maskTableSearchDto.getPageSize());
        params.put("page", maskTableSearchDto.getPage());
        if (StringUtil.isNotEmpty(maskTableSearchDto.getTableName())) {
            params.put("table_name", maskTableSearchDto.getTableName());
        }
        params.put("storeEngine", maskTableSearchDto.getStoreEngine());
        params.put("tenantId", ShiroUtils.getTenantId());
        PageUtils page = tableInfoService.queryUserTablePage(params);
        List<TableInfo> tableInfoTableInfoList = page.getList();
        if (CollectionUtil.isNotEmpty(tableInfoTableInfoList)) {
            List<MaskTableInfoVO> list = PojoUtils.listConvert(MaskTableInfoVO.class, tableInfoTableInfoList);
            page.setList(list);
        }

        return R.okWithPage(page);
    }


    /**
     * 获取所有的配置类别
     */
    @ApiOperation("获取所有的数据库名称")
    @GetMapping("/listDbs")
    public R listDbs() {
        return R.okWithData(DBTypeEnum.values());
    }


    @ApiOperation("数据加密表列表")
    @PostMapping("/encryptTableList")
    public R encryptTableList(@RequestBody MaskTableSearchDto maskTableSearchDto) {
        Map params = new HashMap();
        Long userId = ShiroUtils.getUserId();
        params.put("create_per", userId);
        params.put("appUser", userId);
        params.put("sidx", "id");
        params.put("order", "desc");
        if (StringUtils.isNotBlank(maskTableSearchDto.getDbName())) {
            params.put("db_name", maskTableSearchDto.getDbName());
        }
        if (maskTableSearchDto.getCreateUserId() != null && maskTableSearchDto.getCreateUserId() > 0) {
            params.put("userId", maskTableSearchDto.getCreateUserId());
        }

        params.put("limit", maskTableSearchDto.getPageSize());
        params.put("page", maskTableSearchDto.getPage());
        if (StringUtil.isNotEmpty(maskTableSearchDto.getTableName())) {
            params.put("table_name", maskTableSearchDto.getTableName());
        }
        if (maskTableSearchDto.getStoreEngine() != null && maskTableSearchDto.getStoreEngine() > 0) {
            params.put("store_engine", maskTableSearchDto.getStoreEngine());
        }
        params.put("tenantId", ShiroUtils.getTenantId());
        PageUtils page = tableInfoService.queryUserTablePage(params);
        List<TableInfo> tableInfoTableInfoList = page.getList();
        if (CollectionUtil.isNotEmpty(tableInfoTableInfoList)) {
            List<MaskTableInfoVO> list = PojoUtils.listConvert(MaskTableInfoVO.class, tableInfoTableInfoList);
            page.setList(list);
        }

        return R.okWithPage(page);
    }

    /**
     * 获取获取数据仓库的创建人信息，用于前端筛选
     */
    @ApiOperation("获取获取数据仓库的创建人信息")
    @GetMapping("/createUserList")//  /bdp/tableInfo/userList
    public R createUserList() {
        Map params = new HashMap();
        Long userId = ShiroUtils.getUserId();
        params.put("create_per", userId);
        params.put("appUser", userId);
        params.put("tenantId", ShiroUtils.getTenantId());
        List<Map<String,Object>> userList = tableInfoService.queryUserList(params);
        return R.okWithData(userList);
    }

//    /**
//     * 获取获取数据仓库的创建人信息，用于前端筛选
//     */
//    @ApiOperation("获取获取数据仓库的创建人信息")
//    @GetMapping("/createUserList")//  /bdp/tableInfo/userList
//    public R createUserList() {
//        Map<String, Object> params = Maps.newHashMap();
//        List<TableInfo> list = tableInfoService.selectList(params);
//        fillTableInfo(list);
//        List<Map<String, Object>> userList = Lists.newArrayList();
//        Set<Integer> userIdSet = Sets.newHashSet();
//        for (TableInfo tableInfo : list) {
//            if (tableInfo.getCreatePer() == null
//                    || StringUtils.isEmpty(tableInfo.getCreatePerName())) {
//                continue;
//            }
//            if (!userIdSet.contains(tableInfo.getCreatePer())) {
//                Map<String, Object> user = Maps.newHashMap();
//                user.put("userId", tableInfo.getCreatePer());
//                user.put("userName", tableInfo.getCreatePerName());
//                userList.add(user);
//                userIdSet.add(tableInfo.getCreatePer());
//            }
//        }
//        return R.okWithData(userList);
//    }

    private void fillTableInfo(List<TableInfo> tableInfoList) {
        List<SysUserDto> userList = sysUserService.listAllUsers();
        Map<Long, String> userMap = userList.stream().collect(
                Collectors.toMap(SysUserDto::getUserId, SysUserDto::getUsername));
        for (TableInfo tableInfo : tableInfoList) {
            //添加创建用户的信息
            Long userId = Long.valueOf(tableInfo.getCreatePer());
            tableInfo.setCreatePerName(userMap.get(userId));
        }
    }

}

